/*
 * ByteUtil.java        1.0     2009-6-30  15:16:07
 */
package com.letianpai.common.tool;

import java.io.ByteArrayOutputStream;

/**
 * Created by IntelliJ IDEA.
 * User: Chris.F
 * Date: 2009-6-30
 * Time: 15:16:07
 */
public final class ByteUtil {
    public static String bytesToHex(byte[] b) {
        StringBuffer buf = new StringBuffer("");
        for (byte aB : b) buf.append(byteToHex(aB));
        return buf.toString();
    }

    public static byte[] hexToBytes(String hex) {
        int length = hex.length();
        if (length % 2 != 0) throw new IllegalArgumentException("illegal hex string size");
        ByteArrayOutputStream bos = new ByteArrayOutputStream(length / 2);
        for (int i = 0; i < length; i += 2) {
            char[] hex_digit = new char[2];
            hex_digit[0] = hex.charAt(i);
            hex_digit[1] = hex.charAt(i + 1);
            byte b = 0;
            for (char a : hex_digit) {
                int n;
                if (a >= 48 && a <= 57) n = a - 48;     // 0-9
                else if (a >= 65 && a <= 70) n = a - 55;      // A-F
                else if (a >= 97 && a <= 102) n = a - 87;  // a-f
                else throw new IllegalArgumentException("illegal charactor: " + a);
                b = (byte) (b << 4);
                b = (byte) (b | (n & 0xff));
            }
            bos.write(b);
        }
        return bos.toByteArray();
    }

    public static String byteToHex(byte b) {
        // Returns hex String representation of byte b
        char hexDigit[] = {
                '0', '1', '2', '3', '4', '5', '6', '7',
                '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        char[] array = {hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f]};
        return new String(array);
    }

    public static long b2iu(byte b) {
        return b < 0 ? b & 0x7F + 128 : b;
    }

    public static byte[] concat(byte[]... args) {
        int length = 0;
        for (byte[] arg : args) {
            length += arg.length;
        }
        return concat(length, args);
    }

    public static byte[] concat(int length, byte[]... args) {
        byte[] result = new byte[length];
        int pos = 0;
        for (byte[] arg : args) {
            if (arg.length == 0) continue;
            int copylength = arg.length;
            System.arraycopy(arg, 0, result, pos, copylength);
            pos += copylength;
        }
        return result;
    }

    // The bitwise exclusive-OR of two bit strings X and Y of the same length
    public static byte[] XOR(byte[] arg1, byte[] arg2) {
        assert arg1.length == arg2.length;
        byte[] result = new byte[arg1.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = (byte) (arg1[i] ^ arg2[i]);
        }
        return result;
    }

    // return highest (left-most) len bytes of source
    public static byte[] MSB(byte[] source, int len) {
        byte[] result = new byte[len];
        System.arraycopy(source, 0, result, 0, len);
        return result;
    }

    // return lowest (right-most) len bytes of source
    public static byte[] LSB(byte[] source, int len) {
        byte[] result = new byte[len];
        System.arraycopy(source, source.length - len, result, 0, len);
        return result;
    }

    public static byte[] convertNumToBytes(Number number, int byteNumber) {
        byte[] result = new byte[byteNumber];
        long temp = number.longValue();
        for (int i = byteNumber; i > 0; i--) {
            result[i - 1] = (byte) temp;
            temp = temp >> 8;
        }
        return result;
    }

    public static Number convertBytesToNum(byte[] number) {
        long result = 0;
        for (byte aNumber : number) {
            result = result << 8;
            result = result | (aNumber & 0xff);
        }
        return result;
    }

    public static byte[] sub(byte[] source, int begin) {
        if (source == null)
            return null;
        if (source.length == 0)
            return new byte[0];
        if (begin + 1 > source.length)
            throw new IllegalArgumentException("begin position out of range: " + begin);
        int length = source.length - begin;
        byte[] sub = new byte[length];
        System.arraycopy(source, begin, sub, 0, length);
        return sub;
    }

    public static byte[] sub(byte[] source, int begin, int length) {
        if (source == null)
            return null;
        if (source.length == 0)
            return new byte[0];
        if (begin + 1 > source.length)
            throw new IllegalArgumentException("begin position out of range: " + begin);
        if (begin + length > source.length)
            throw new IllegalArgumentException("length out of range: " + length);
        byte[] sub = new byte[length];
        System.arraycopy(source, begin, sub, 0, length);
        return sub;
    }
}
